#include "stdafx.h"
#include "..\headers\CameraComponents.h"
#include "..\headers\GameObject.h"
#include "..\headers\InputSystem.h"
#include "..\headers\GameTime.h"

namespace ne{

CameraComponent::CameraComponent() : 
m_sceneManager(nullptr),
m_camera(nullptr){m_type|=COMPONENT_CAMERA;}
CameraComponent::~CameraComponent(){}

int CameraComponent::s_counter = 0;

void CameraComponent::Init(){
	m_sceneManager=GameObject::GetSceneManager();
	m_camera=m_sceneManager->createCamera("Camera"+Convert::NumberToString(s_counter));
	m_cameraNode=m_owner->GetSceneNode()->createChildSceneNode();
	m_cameraNode->setPosition(0.0f,0.0f,0.0f);
	m_cameraNode->attachObject(m_camera);
	s_counter++;
}

void CameraComponent::Shut(){
	if (m_camera){
		m_sceneManager->destroyCamera(m_camera);
		m_camera = nullptr;
	}
}

Ogre::Vector3 CameraComponent::GetDirection(){return m_camera->getDirection();}
void CameraComponent::SetPosition(float x,float y,float z){m_cameraNode->setPosition(x,y,z);}
void CameraComponent::SetPosition(const Ogre::Vector3& pos){m_cameraNode->setPosition(pos);}
Ogre::Vector3 CameraComponent::GetPosition()const{return m_cameraNode->getPosition();}
Ogre::Vector3 CameraComponent::GetDerivedPosition()const{return m_cameraNode->_getDerivedPosition();}

FirstPersonCameraComponent::FirstPersonCameraComponent():m_inputSystem(nullptr){
	m_type|=COMPONENT_FIRST_PERSON_CAMERA;
	m_forward=OIS::KC_W;
	m_backward=OIS::KC_S;
	m_left=OIS::KC_A;
	m_right=OIS::KC_D;
	m_down=OIS::KC_PGDOWN;
	m_up=OIS::KC_PGUP;
	m_control=false;
	m_limit=false;
	m_rotSpeed=1.0f;
	m_pitch=0.0f;
	m_yaw=0.0f;
	m_pitchLimit=90.0f;
	m_movementSpeed=50.0f;
	m_translation=Ogre::Vector3::ZERO;
	
}

void FirstPersonCameraComponent::Init(){
	m_inputSystem=GameObject::GetInputSystem();
	CameraComponent::Init();
}

void FirstPersonCameraComponent::Update(GameTime* gameTime){
	float pitchAngle = 0.0f, pitchAngleSign = 0.0f;
	float rotationSpeed = m_rotSpeed * gameTime->DeltaTime();
	float angle = 90.0f;

	m_yaw+=Ogre::Radian(m_inputSystem->GetMouseState().X.rel * rotationSpeed);
	m_pitch+=Ogre::Radian(m_inputSystem->GetMouseState().Y.rel * rotationSpeed);

	m_camera->setOrientation(Ogre::Quaternion::IDENTITY);
	m_camera->yaw(-m_yaw);
	m_camera->pitch(-m_pitch);

	m_cameraNode->translate(m_camera->getOrientation() * m_translation,Ogre::SceneNode::TS_LOCAL);
	if (m_limit){
		if(m_pitch.valueDegrees()<(-m_pitchLimit.valueDegrees())){
			m_camera->setOrientation(Ogre::Quaternion::IDENTITY);
			m_camera->yaw(-m_yaw);
			m_camera->pitch(m_pitchLimit);
			m_pitch=(-m_pitchLimit.valueRadians());
		}
		else if(m_pitch.valueDegrees()>m_pitchLimit.valueDegrees()){
			m_camera->setOrientation(Ogre::Quaternion::IDENTITY);
			m_camera->yaw(-m_yaw);
			m_camera->pitch(-m_pitchLimit);
			m_pitch=(m_pitchLimit.valueRadians());
		}
	}
	if (m_control){
		float vel = m_movementSpeed*gameTime->DeltaTime();
		if (m_inputSystem->IsKeyDown(OIS::KC_LSHIFT)){
			vel *= 2.0f;
		}
		if (m_inputSystem->IsKeyDown(m_up)){
			m_cameraNode->setPosition(m_cameraNode->getPosition()+Ogre::Vector3(0.0f,vel,0.0f));
		}
		else if (m_inputSystem->IsKeyDown(m_down)){
			m_cameraNode->setPosition(m_cameraNode->getPosition()-Ogre::Vector3(0.0f,vel,0.0f));
		}
		if (m_inputSystem->IsKeyDown(m_forward)){
			m_translation.z = -vel;
		}
		else if (m_inputSystem->IsKeyDown(m_backward)){
			m_translation.z = vel;
		}
		else {
			m_translation.z = 0.0f;
		}
		if (m_inputSystem->IsKeyDown(m_left)){
			m_translation.x = -vel;
		}
		else if (m_inputSystem->IsKeyDown(m_right)){
			m_translation.x = vel;
		}
		else {
			m_translation.x = 0.0f;
		}
		if (m_inputSystem->IsKeyPressed(OIS::KC_Z)){
			std::cout<<m_cameraNode->getPosition()<<"\n";
		}
	}
}

ThirdPersonCameraComponent::ThirdPersonCameraComponent(){
	m_inputSystem=nullptr;
	m_target=nullptr;
	m_sceneManager=nullptr;
	m_camera=nullptr;
	m_cameraNode=nullptr;
	m_cameraPivot=nullptr;
	m_pivotPitch=0.0f;
	m_cameraHeight=1.0f;
	m_pitch=0.0f;
	m_yaw=0.0f;
	m_pitchLimit=80.0f;
	m_horSpeed=1.0f;
	m_verSpeed=1.0f;
	m_minZoomDist=2.0f;
	m_maxZoomDist=20.0f;
	m_zoomSpeed=1.0f;
}
ThirdPersonCameraComponent::~ThirdPersonCameraComponent(){}

void ThirdPersonCameraComponent::Init(){
	m_sceneManager=GameObject::GetSceneManager();
	m_inputSystem=GameObject::GetInputSystem();
	m_camera=m_sceneManager->createCamera("Camera"+Convert::NumberToString(s_counter));
	m_camera->setPosition(0,0,0);
	m_cameraPivot=m_sceneManager->getRootSceneNode()->createChildSceneNode();
	//m_cameraNode->setFixedYawAxis(true);
	//m_cameraPivot->setFixedYawAxis(true);
	m_cameraNode=m_cameraPivot->createChildSceneNode(Ogre::Vector3(0,m_cameraHeight,m_maxZoomDist));
	m_cameraNode->attachObject(m_camera);
}

void ThirdPersonCameraComponent::Update(GameTime* gameTime){
	if(!m_target){return;}
	float x=((float)(m_inputSystem->GetMouseState().X.rel*m_horInvert))*(m_horSpeed*gameTime->DeltaTime());
	float y=((float)(m_inputSystem->GetMouseState().Y.rel*m_verInvert))*(m_verSpeed*gameTime->DeltaTime());
	float z=((float)m_inputSystem->GetMouseState().Z.rel)*(m_zoomSpeed*gameTime->DeltaTime());
	UpdateCameraGoal(x,y,-z);
	m_cameraPivot->setPosition(m_target->getPosition());
	m_camera->lookAt(m_cameraPivot->getPosition());
}

void ThirdPersonCameraComponent::UpdateCameraGoal(float p_deltaYaw,float p_deltaPitch,float p_deltaZoom){
	m_yaw+=Ogre::Radian(p_deltaYaw);
	m_pitch+=Ogre::Radian(p_deltaPitch);

	m_cameraPivot->setOrientation(Ogre::Quaternion::IDENTITY);
	m_cameraPivot->yaw(m_yaw);
	m_cameraPivot->pitch(m_pitch);
	if(m_pitch.valueDegrees()<(-m_pitchLimit.valueDegrees())){
		m_cameraPivot->setOrientation(Ogre::Quaternion::IDENTITY);
		m_cameraPivot->yaw(m_yaw);
		m_cameraPivot->pitch(-m_pitchLimit);
		m_pitch=(-m_pitchLimit.valueRadians());
	}
	else if(m_pitch.valueDegrees()>(m_pitchLimit.valueDegrees())){
		m_cameraPivot->setOrientation(Ogre::Quaternion::IDENTITY);
		m_cameraPivot->yaw(m_yaw);
		m_cameraPivot->pitch(m_pitchLimit);
		m_pitch=m_pitchLimit.valueRadians();
	}
	if(p_deltaZoom!=0.0f){
		float currZoom=m_cameraNode->getPosition().z;
		currZoom+=p_deltaZoom;
		if(currZoom<m_minZoomDist){currZoom=m_minZoomDist;}
		else if(currZoom>m_maxZoomDist){currZoom=m_maxZoomDist;}
		m_cameraNode->setPosition(Ogre::Vector3(0,m_cameraHeight,currZoom));
	}
}

Ogre::Vector3 ThirdPersonCameraComponent::GetDirectionFromCamera(Ogre::Vector3 p_dir){
	if(p_dir!=Ogre::Vector3::ZERO){
		Ogre::Vector3 goalDir=p_dir;
		Ogre::Vector3 cameraDir=m_camera->getDirection();
		goalDir=(m_cameraPivot->getOrientation()*goalDir);
		goalDir.y=0.0f;
		goalDir.normalise();
		Ogre::Quaternion quat;
		return goalDir;
	}
	return Ogre::Vector3::ZERO;
}

void ThirdPersonCameraComponent::SetVerticalInvert(bool p_value){
	if(p_value){m_verInvert=1;}
	else{m_verInvert=(-1);}
}

bool ThirdPersonCameraComponent::IsVerticalInvert()const{return (m_verInvert==1)?true:false;}
bool ThirdPersonCameraComponent::IsHorizontalInvert()const{return (m_horInvert==1)?true:false;}

void ThirdPersonCameraComponent::SetHorizontalInvert(bool p_value){
	if(p_value){m_horInvert=1;}
	else{m_horInvert=(-1);}
}

void ThirdPersonCameraComponent::SetCameraInvert(bool p_value){
	if(p_value){m_horInvert=1;m_verInvert=1;}
	else{m_horInvert=(-1);m_verInvert=(-1);}
}


} // namespace ne